CS 211 Lesson 22
Structure Arrays
Quote:
You have not lived a perfect day, even though you have earned your money, unless you have done something for someone who will never be able to repay you. Ruth Schmeltzer
Lesson Objectives:
Understand the difference between normal arrays and structure arrays
Be able to create a structure array
Be able to access and change fields within a structure array
Lesson:
I. MATLAB Concepts
A. Introduction to non-homogeneous arrays (a review from last lesson)
Up to this point in this course, all arrays have held values of a single data type. That is, an array contained all double precision values, or all character values, or all integer values, but never a mixture of these different data types.
Now we introduce two new data structures that can store values of possibly different data types in a single structure. They are:
cell arrays, which access elements within them using indexes (subscripts)
structure arrays, which access elements within them using field names
These two data structures can be nested, meaning you can have a cell array that contains structure arrays that contains other structure arrays that contain other cell arrays, etc. You can create arbitrarily complex data relationships by nesting cell and structure arrays.
You typically organize data into cell arrays if you need to access the various element values using a numerical subscript (or index).
You typically organize data into structure arrays when the various values are best accessed using a descriptive name (called the field name).
B. Overview of structures
A structure is data structure that contains named elements called fields.
Structures and "normal" arrays are compared in the following table:
"Normal" arrays Structures Elements are identified by an index (position/subscript) that gives its location within the array a field name Data types all elements must be the same data type (i.e., homogeneous) each field can be any data type (i.e., heterogeneous)
Structures are useful for holding a collection of related values, even if the values are of different data types.
For example, below is a set of related values that describe an individual cadet:
Field Name Field Value Social 123456789 Year 2009 First_name John Last_name Doe Squadron 13 This related data can be stored in a single structure using the following MATLAB statements:
Cadet.Social = '123456789';
Cadet.Year = 2009;
Cadet.First_name = 'John';
Cadet.Last_name = 'Doe';
Cadet.Squadron = 13;
Individual field values are referenced by specifying a structure variable name, followed by a period, followed by the field name.
A field of a structure can contain a scalar, a vector, a matrix, a cell array, or another structure. The ability to "nest" structures inside structures allows you to create arbitrarily complex data structures.
C. Overview of structure arrays
A structure array is an array of structures (surprise!).
One method of creating structure arrays is with assignment statements for each field.
For example, the following code makes Cadet a 2-element structure array:
Cadet(1).Social = '123456789';
Cadet(1).Year = 2009;
Cadet(1).First_name = 'John';
Cadet(1).Last_name = 'Doe';
Cadet(1).Squadron = 13;
Cadet(2).Social = '234567890';
Cadet(2).Year = 2011;
Cadet(2).First_name = 'Jane';
Cadet(2).Last_name = 'Doe';
Cadet(2).Squadron = 5;
In the example code above:
The name of the variable containing the structure array is Cadet.
Cadet is an array with 2 elements.
Each element of Cadet is a structure with 5 fields.
The five fields of the structure are named: Social, Year, First_name, Last_name, and Squadron .
Another method of creating structure arrays is by using the struct(field_name, value, ...) function.
For example, the 2-element structure array called Cadet above could have been created by:
Cadet(1) = struct('Social', '123456789', ...
'Year', 2009, ...
'First_name', 'John', ...
'Last_name', 'Doe', ...
'Squadron', 13);
Cadet(2) = struct('Social', '234567890', ...
'Year', 2011, ...
'First_name', 'Jane', ...
'Last_name', 'Doe', ...
'Squadron', 5);
New elements can be added to a structure array dynamically by using an index that is larger than the current structure array size. However, this is not efficient and can slow down the time it takes your code to execute.
If you know the size of the structure array you need, pre-allocate the entire structure before assigning any values to the element fields. This will speed up the execution of your code. For example, the following code creates a 1200-element structure array with most of the fields empty, but with the year field set to 2009 in all 1200 structures (Note: this is no longer true with MATLAB R2007 which sets just the 1200th value to the given value).
Cadet(1200) = struct('Social', [], ...
'Year', 2009, ...
'First_name', [], ...
'Last_name', [], ...
'Squadron', []);
If you add a field to an individual structure in a structure array, that field is added to all structures in the array. For example, the statement:
Cadet(10).Home_town = 'Santa Cruz';
would add the field called Home_town to all 1200 elements of the Cadet structure array. Only the 10th element in the array would have a value for its Home_town field. All other elements in the Cadet structure array would have "empty" vectors, i.e., [], for their Home_town field values.
D. Accessing values stored in structure arrays
If a structure array has only one element, then only the field name is needed to access a value. For example, if Cadet contained only one element:
fprintf('%s has SS# %s', Cadet.Last_name, Cadet.Social);
If a structure array contains more than one element, then an index number and a field name is needed to access a value. For example, if Cadet contained many elements and j was a valid index:
fprintf('%s has SS# %s', Cadet(j).Last_name, Cadet(j).Social);
If you would like to "gather up" all of the values of a field from different elements into a single vector, you can use the syntax [Structure_array_name.field_name]. For example, the following would count the number of cadets who are members of the class of 2009:
Size_of_class_of_2009 = sum( [Cadet.Year] == 2009 );
The previous method of "gathering up" values from a structure array does not work well for character data because all of the characters become concatenated together to form one huge string. Instead, if you want to "gather up" a set of strings from a structure array, you can create a cell array where each string is placed in a unique cell of the cell array. Use the syntax {Structure_array_name.field_name} to create a cell array. For example, the following would search all the cadet records for a matching name:
Matching_rows = strmatch( Desired_name, {Cadet.Last_name} );
E. Advanced structure array concepts (optional material that will never be tested on a GR)
The function fieldnames() returns a structure's field names as a cell array of strings.
The function getfield(Structure, Element_index, Field_name) may be used to get the value from a field in a structure array. This allows you to use a variable that contains a field name to access data in a structure array. This access method is slow and should generally not be used. The syntax Structure(Element_index).Field_name is equivalent (as long as the field name is static).
The function setfield(Structure, Element_index, Field_name, Value) may be used to set the value of a field in a structure array. It is not efficient and should be used only when the field name is a variable.
II. Good Programming Practices
For efficiency:
Pre-allocate structure arrays before assigning individual values to its element's fields.
Avoid creating new fields for an existing structure array.
Create all fields initially with a struct()
function call.
To make your code more readable:
Always use very descriptive names for your field names.
Avoid grouping values into a structure if the values are not related in any way.
III. Algorithms
The code in struct_demo.m demonstrates the creation and usage of a very simple structure array.
Lab Work: Lab 22
References: Chapman Textbook: section 7.3